/* 
1.什么是Promise？发布订阅模式 它是设计模式的其中一种
2.面试经常问的 其次手写这个 它的思想被人们广泛所使用的
3.有谁在用 vue2 eventBus $on监听 $emit触发（派发）
4.electron ipcRenderer（事件总线） ipcMain(通信)
5.DOM2 addEventListener removeEventListener 
*/

/* document.addEventListener("click", function(event) {
  console.log("点击了");
});

// 声明事件对象
const cbTest = () => {
  console.log("触发了");
}

// 监听器
document.addEventListener("addadsadsa", cbTest, {
  once: true
});

// 移除事件
document.removeEventListener("addadsadsa", cbTest);

const eventFun = new Event("addadsadsa");

document.dispatchEvent(eventFun);
document.dispatchEvent(eventFun); 
document.dispatchEvent(eventFun); 
document.dispatchEvent(eventFun); */

// 监听器
// 实现 once on emit off 订阅中心Map<事件的名称， [Function]订阅者集合>
interface I {
  events: Map<string, Function[]>,
  once:(event: string, callback: Function) => void,   // 触发一次订阅器
  on: (event: string, callback: Function) => void,   // 订阅
  emit: (event: string, ...args: any[]) => void,  // 发布派发
  off: (event: string, callback: Function) => void,  // 移除删除订阅
}

class Emitter implements I {
  events: Map<string, Function[]>

  constructor() {
    this.events = new Map();
  }

  once(event: string, callback: Function) {
    // 1.创建一个自定义函数 通过on触发
    // 2.触发完之后立马通过off回收掉

    const cb = (...args: any[]) => {
      callback(...args)
      this.off(event, cb)
    }

    this.on(event, cb);
  }
  on(event: string, callback: Function) {
    // 如果已经存在
    if(this.events.has(event)) {
      const calbackList = this.events.get(event);
      calbackList?.push(callback)
    } else {
      // 否则就是第一次存
      this.events.set(event, [callback])
    }
  }
  emit(event: string, ...args: any[]) {
    const calbackList = this.events.get(event);
    // console.log(calbackList);
    if (calbackList && calbackList.length > 0) {
      calbackList.forEach(cb => {
        cb(...args);
      });
    }
  }
  off(event:string, callback: Function) {
    const callbackList = this.events.get(event);
    if(callbackList) {
      callbackList.splice(callbackList.indexOf(callback), 1)
    }
  }
}

const bus = new Emitter();

const busFn = (b: boolean, s: string) => {
  console.log(1, b, s)
}

/* bus.on("message", busFn);

bus.on("off", busFn); */

bus.once("message", busFn);

bus.emit("message", false, 213213);
bus.emit("message", false, 213213);
bus.emit("message", false, 213213);
bus.emit("message", false, 213213);
bus.emit("message", false, 213213);

console.log(bus);
